package utils;

import entity.item;
import entity.taskInfo;
import entity.worker;
import pojo.TaskAssignment;

import java.time.LocalDate;
import java.util.*;

/**
 * 处理任务流程的类，负责根据产能分配任务
 */
public class HandleTaskflow {
    private Map<Integer, Double> workcenterCapacities;  // 每月产能
    private Map<Integer, List<TaskAssignment>> monthlyDemands;  // 初始每月需求
    private Map<Integer, List<TaskAssignment>> overflowTasks;  // 溢出任务
    private List<TaskAssignment> outsourcedTasks;  // 外包任务
    private Map<Integer, List<TaskAssignment>> finalTasks;  // 最终任务列表
    private String workcenterName;
    private int year;
    private DateHandle dateHandler;  // 使用DateHandle处理日期相关操作

    /**
     * 构造函数
     */
    public HandleTaskflow(Map<Integer, Double> workcenterCapacities,
                          Map<Integer, List<TaskAssignment>> monthlyDemands,
                          String workcenterName,
                          int year,
                          List<item> items,
                          List<taskInfo> taskInfos,
                          List<worker> workers) {
        if (workcenterCapacities == null || monthlyDemands == null) {
            throw new IllegalArgumentException("工作中心产能、月度需求和日期处理器不能为空");
        }

        this.workcenterCapacities = new HashMap<>(workcenterCapacities);
        this.monthlyDemands = new HashMap<>();
        for (Map.Entry<Integer, List<TaskAssignment>> entry : monthlyDemands.entrySet()) {
            this.monthlyDemands.put(entry.getKey(), new ArrayList<>(entry.getValue()));
        }

        this.outsourcedTasks = new ArrayList<>();
        this.overflowTasks = new HashMap<>();
        this.finalTasks = new HashMap<>();
        this.workcenterName = workcenterName;
        this.year = year;
        this.dateHandler = new DateHandle(workers, taskInfos, items);

        System.out.println("初始化任务流处理器 - 工作中心: " + workcenterName + ", 年份: " + year);
    }

    // Getters and Setters
    public String getWorkcenterName() {
        return workcenterName;
    }

    public int getYear() {
        return year;
    }

    public Map<Integer, Double> getWorkcenterCapacities() {
        return workcenterCapacities;
    }

    public Map<Integer, List<TaskAssignment>> getMonthlyDemands() {
        return monthlyDemands;
    }

    public Map<Integer, List<TaskAssignment>> getOverflowTasks() {
        return overflowTasks;
    }

    public List<TaskAssignment> getOutsourcedTasks() {
        return outsourcedTasks;
    }

    public Map<Integer, List<TaskAssignment>> getFinalTasks() {
        return finalTasks;
    }

    /**
     * 根据工作日计算产能
     * @param month 月份
     * @param dailyCapacity 日产能,默认8小时
     */
    public double calculateMonthlyCapacity(int month, double dailyCapacity) {
        validateMonth(month);
        if (dailyCapacity < 0) {
            throw new IllegalArgumentException("日产能不能为负数: " + dailyCapacity);
        }
        // 利用DateHandle计算工作日
        double workCenterCapacity = dateHandler.calculateWorkcenterWorkload(workcenterName, year, month);
        if (workCenterCapacity <= 0) {
            // 如果DateHandle未返回有效值，使用备用计算方法
            int workingDays = calculateBackupWorkingDays(month);
            workCenterCapacity = workingDays * dailyCapacity;
            System.out.println("使用备用方法计算第" + month + "月产能: " + workingDays + " 工作日 * " + dailyCapacity + " = " + workCenterCapacity);
        } else {
            System.out.println("使用DateHandle计算第" + month + "月产能: " + workCenterCapacity);
        }

        workcenterCapacities.put(month, workCenterCapacity);
        return workCenterCapacity;
    }

    /**
     * 备用方法：计算工作日数量
     */
    private int calculateBackupWorkingDays(int month) {
        // 一般一个月按22个工作日计算（备用方法）
        return 22;
    }

    /**
     * 处理月度溢出任务
     */
    private void handleMonthlyOverflow(int currentMonth) {
        validateMonth(currentMonth);

        double capacity = workcenterCapacities.getOrDefault(currentMonth, 0.0);
        System.out.println("处理第" + currentMonth + "月 - 初始产能: " + capacity);

        // 使用集合来跟踪已处理的任务，避免重复
        Set<String> processedTaskIds = new HashSet<>();

        // 1. 优先处理溢出任务
        List<TaskAssignment> overflowList = overflowTasks.getOrDefault(currentMonth, new ArrayList<>());
        List<TaskAssignment> processedOverflowTasks = new ArrayList<>();

        if (!overflowList.isEmpty()) {
            System.out.println("第" + currentMonth + "月溢出任务数: " + overflowList.size());

            // 按截止日期排序
            overflowList.sort(Comparator.comparing(TaskAssignment::getDeadline));

            // 计算溢出
            List<TaskAssignment> overflowOverflow = calculateOverflow(overflowList, capacity);

            // 成功处理的溢出任务
            processedOverflowTasks.addAll(overflowList);

            // 记录处理的任务ID
            for (TaskAssignment task : processedOverflowTasks) {
                String taskId = task.getOrderCode() + "-" + task.getItemID() + "-" + task.getDeadline();
                processedTaskIds.add(taskId);
            }

            if (!processedOverflowTasks.isEmpty()) {
                // 添加到最终任务列表
                if (finalTasks.containsKey(currentMonth)) {
                    finalTasks.get(currentMonth).addAll(processedOverflowTasks);
                } else {
                    finalTasks.put(currentMonth, new ArrayList<>(processedOverflowTasks));
                }
                System.out.println("第" + currentMonth + "月处理的溢出任务数: " + processedOverflowTasks.size());
            }

            // 更新剩余产能
            capacity = calculateRemainingCapacity(capacity, processedOverflowTasks);
            System.out.println("处理溢出任务后剩余产能: " + capacity);

            // 处理溢出任务产生的新溢出
            if (!overflowOverflow.isEmpty()) {
                System.out.println("第" + currentMonth + "月无法处理的溢出任务数: " + overflowOverflow.size());

                if (currentMonth == 1) {
                    // 第1月无法处理的任务直接外包
                    outsourcedTasks.addAll(overflowOverflow);
                    System.out.println("添加到外包任务: " + overflowOverflow.size());
                } else {
                    // 其他月份的溢出传递给前一个月
                    int prevMonth = currentMonth - 1;
                    overflowTasks.computeIfAbsent(prevMonth, k -> new ArrayList<>()).addAll(overflowOverflow);
                    System.out.println("转移到第" + prevMonth + "月: " + overflowOverflow.size());
                }
            }
        }

        // 2. 处理当月原始任务
        if (capacity > 0) {
            // 获取当月原始任务，排除已处理的溢出任务
            List<TaskAssignment> currentMonthTasks = new ArrayList<>();
            for (TaskAssignment task : monthlyDemands.getOrDefault(currentMonth, new ArrayList<>())) {
                String taskId = task.getOrderCode() + "-" + task.getItemID() + "-" + task.getDeadline();
                if (!processedTaskIds.contains(taskId)) {
                    currentMonthTasks.add(task);
                }
            }
            if (!currentMonthTasks.isEmpty()) {
                System.out.println("第" + currentMonth + "月原始任务数: " + currentMonthTasks.size());

                // 按截止日期排序（升序，优先处理截止日期靠前的）
                currentMonthTasks.sort(Comparator.comparing(TaskAssignment::getDeadline));

                // 计算当月原始任务的溢出
                List<TaskAssignment> currentMonthOverflow = calculateOverflow(currentMonthTasks, capacity);

                // 添加成功处理的任务到最终任务列表
                if (!currentMonthTasks.isEmpty()) {
                    if (finalTasks.containsKey(currentMonth)) {
                        finalTasks.get(currentMonth).addAll(currentMonthTasks);
                    } else {
                        finalTasks.put(currentMonth, new ArrayList<>(currentMonthTasks));
                    }
                    System.out.println("第" + currentMonth + "月处理的原始任务数: " + currentMonthTasks.size());
                }

                // 处理当月任务的溢出
                if (!currentMonthOverflow.isEmpty()) {
                    System.out.println("第" + currentMonth + "月无法处理的原始任务数: " + currentMonthOverflow.size());

                    if (currentMonth == 1) {
                        // 第1月无法处理的任务直接外包
                        outsourcedTasks.addAll(currentMonthOverflow);
                        System.out.println("添加到外包任务: " + currentMonthOverflow.size());
                    } else {
                        // 其他月份的溢出传递给前一个月
                        int prevMonth = currentMonth - 1;
                        overflowTasks.computeIfAbsent(prevMonth, k -> new ArrayList<>()).addAll(currentMonthOverflow);
                        System.out.println("转移到第" + prevMonth + "月: " + currentMonthOverflow.size());
                    }
                }
            }
        } else {
            // 产能不足，需要将所有原始任务传递给前一个月
            List<TaskAssignment> remainingTasks = new ArrayList<>();
            for (TaskAssignment task : monthlyDemands.getOrDefault(currentMonth, new ArrayList<>())) {
                String taskId = task.getOrderCode() + "-" + task.getItemID() + "-" + task.getDeadline();
                if (!processedTaskIds.contains(taskId)) {
                    remainingTasks.add(task);
                }
            }

            if (!remainingTasks.isEmpty()) {
                System.out.println("第" + currentMonth + "月产能不足，无法处理的原始任务数: " + remainingTasks.size());

                if (currentMonth == 1) {
                    // 第1月无法处理的任务直接外包
                    outsourcedTasks.addAll(remainingTasks);
                    System.out.println("添加到外包任务: " + remainingTasks.size());
                } else {
                    // 其他月份的任务传递给前一个月
                    int prevMonth = currentMonth - 1;
                    overflowTasks.computeIfAbsent(prevMonth, k -> new ArrayList<>()).addAll(remainingTasks);
                    System.out.println("转移到第" + prevMonth + "月: " + remainingTasks.size());
                }
            }
        }

        // 清空当月处理完的数据，避免重复处理
        monthlyDemands.put(currentMonth, new ArrayList<>());
        overflowTasks.put(currentMonth, new ArrayList<>());

        // 添加验证日志
        if (finalTasks.containsKey(currentMonth)) {
            double totalMonthWorkload = 0;
            for (TaskAssignment task : finalTasks.get(currentMonth)) {
                totalMonthWorkload +=task.getMakeCycle()*task.getAssignedQuantity(); // 使用统一的工时计算方法
            }
            System.out.println("第" + currentMonth + "月最终分配: " + finalTasks.get(currentMonth).size() +
                    "项任务, 总工时: " + String.format("%.2f", totalMonthWorkload));
        }
    }
    /**
     * 计算溢出任务
     */
    private List<TaskAssignment> calculateOverflow(List<TaskAssignment> tasks, double capacity) {
        List<TaskAssignment> overflow = new ArrayList<>();
        double originalCapacity = capacity;
        List<TaskAssignment> processedTasks = new ArrayList<>();
        double n=0;
        for (TaskAssignment task : tasks) {
            n+=task.getAssignedQuantity();
        }
        System.out.println("n = " + n);

        // 定义公式参数
//        final double M = 0.4669;
//        final double alpha = -0.2099;
        final double M = 0.191309;
        final double alpha = -1.075812;

//        final double M = 0.5754;
//        final double alpha = -0.4245;
        double number=0;
        double flowNumber=0;
        for (int i = 0; i <tasks.size(); i++) {
            TaskAssignment task = tasks.get(i);
            double prepareTime = 0;
            double baseMakeTime = task.getMakeCycle();

            if (baseMakeTime <0 && prepareTime <0) {
                continue;
            }
            // 计算实际加工时间
            double totalProcessTime = prepareTime;
            for (int r = 1; r <= task.getAssignedQuantity(); r++) {
                double factor = M + (1 - M) * Math.pow(r, alpha);
                totalProcessTime += factor * baseMakeTime;
            }
            if (totalProcessTime <= capacity) {
                // 可以完全处理
                capacity -= totalProcessTime;
                processedTasks.add(task);
                number+=task.getAssignedQuantity();
            } else if (prepareTime < capacity) {
                // 可以开始任务，但无法完全处理
                capacity -= prepareTime;
                // 计算剩余产能可以处理的数量
                int canProcess = 0;
                double remainingCapacity = capacity;
                while (canProcess < task.getAssignedQuantity()) {
                    double factor = M + (1 - M) * Math.pow(canProcess + 1, alpha);
                    double nextItemTime = factor * baseMakeTime;
                    if (remainingCapacity >= nextItemTime) {
                        remainingCapacity -= nextItemTime;
                        canProcess++;
                    } else {
                        break;
                    }
                }
                if (canProcess > 0) {
                    // 可以部分处理
                    TaskAssignment splitTask = createOverflowTask(task, task.getAssignedQuantity() - canProcess);
                    task.setAssignedQuantity(canProcess);
                    capacity = remainingCapacity;
                    processedTasks.add(task);
                    overflow.add(splitTask);
                    number+=canProcess;
                    flowNumber+=splitTask.getAssignedQuantity();
                    //System.out.println("任务拆分: " + task.getItemID() + " - 处理数量: " + canProcess + ", 溢出数量: " + splitTask.getAssignedQuantity()+"  ddl"+splitTask.getDeadline());
                } else {
                    // 准备时间消耗完所有产能，无法处理任何数量
                    capacity += prepareTime;
                    overflow.add(task);
                    flowNumber+=task.getAssignedQuantity();
                    //System.out.println("任务溢出(仅消耗准备时间): " + task.getItemID() + " - 数量: " + task.getAssignedQuantity()+"  ddl"+task.getDeadline());
                }
            } else {
                // 准备时间都无法满足，完全溢出
                overflow.add(task);
                flowNumber+=task.getAssignedQuantity();
                //System.out.println("任务溢出(无法开始): " + task.getItemID() + " - 数量: " + task.getAssignedQuantity()+"  ddl"+task.getDeadline());
            }
        }
        System.out.println("计算溢出 - 初始产能: " + originalCapacity + ", 剩余产能: " + capacity + ", 溢出任务数: " + overflow.size());
        System.out.println("处理了"+number+"个零件");
        System.out.println("溢出了"+flowNumber+"个零件");
        tasks.clear();
        tasks.addAll(processedTasks);
        return overflow;
    }

    /**
     * 计算剩余产能
     */
    private double calculateRemainingCapacity(double initialCapacity, List<TaskAssignment> completedTasks) {
        double usedCapacity = 0;
//        final double M = 0.4669;
//        final double alpha = -0.2099;

        final double M = 0.191309;
        final double alpha = -1.075812;

//        final double M = 0.5754;
//        final double alpha = -0.4245;
        for (TaskAssignment task : completedTasks) {
            // 添加准备时间
            usedCapacity += 0;

            // 计算实际加工时间
            double baseMakeTime = task.getMakeCycle();
            for (int r = 1; r <= task.getAssignedQuantity(); r++) {
                double factor = M + (1 - M) * Math.pow(r, alpha);
                usedCapacity += factor * baseMakeTime;
            }
        }

        return Math.max(0, initialCapacity - usedCapacity);
    }

    /**
     * 创建溢出任务
     */
    private TaskAssignment createOverflowTask(TaskAssignment original, int quantity) {
        return new TaskAssignment(
                original.getItemID(),
                original.getOrderCode(),
                original.getFlowOrderCode(),
                original.getItemName(),
                original.getItemDifficulty(),
                original.getWorkcenterName(),
                quantity,
                original.getPreCycle(),
                original.getMakeCycle(),
                original.getDeadline()
        );
    }

    /**
     * 验证月份有效性
     */
    private void validateMonth(int month) {
        if (month < 1 || month > 12) {
            throw new IllegalArgumentException("月份必须在1-12之间，收到: " + month);
        }
    }

    /**
     * 根据月份加载任务
     * 使用DateHandle的handleTaskInfo方法加载当月任务
     */
    public Map<Integer,Map<String,Double>> loadMonthlyTasks(int month) {
        validateMonth(month);
        Map<Integer,Map<String,Double>> res=new HashMap<>();
        // 使用DateHandle获取当月任务
        List<TaskAssignment> tasks = dateHandler.handleTaskInfo(workcenterName, month);
        double totalTime=0;
        double number=0;
        for (TaskAssignment task : tasks) {
            totalTime += task.getMakeCycle()*task.getAssignedQuantity();
            number+=task.getAssignedQuantity();
        }
        System.out.println("第"+month+"月需求为"+totalTime+"工时");
        System.out.println("第"+month+"月需求为"+number+"数量");

        if (tasks != null && !tasks.isEmpty()) {
            monthlyDemands.put(month, tasks);
            System.out.println("加载第" + month + "月任务: " + tasks.size() + " 项");
        } else {
            System.out.println("第" + month + "月没有找到任务");
            monthlyDemands.put(month, new ArrayList<>());
        }
        Map<String,Double> map=new HashMap<>();
        map.put("工时", totalTime);
        map.put("件数", number);
        res.put(month,map);
        return res;
    }

    /**
     * 生成处理报告
     */
    private void generateProcessingReport() {
        System.out.println("=== 各月最终任务分配 ===");
        List<Integer> months = new ArrayList<>(finalTasks.keySet());
        Collections.sort(months);
        for (int month : months) {
            List<TaskAssignment> monthTasks = finalTasks.get(month);
            System.out.println("第 " + month + " 月任务：数量 " + monthTasks.size());

            double totalWorkload = 0;
            double number=0;
            for (TaskAssignment task : monthTasks) {
                totalWorkload += task.getMakeCycle() * task.getAssignedQuantity();
                number+=task.getAssignedQuantity();
               // System.out.println("任务: " + task.getOrderCode() + ", 图号: " + task.getItemID() +
                       // ", 数量: " + task.getAssignedQuantity() + ", 工时: " + (task.getMakeCycle() * task.getAssignedQuantity())+"截至日期"+task.getDeadline());
            }
            System.out.println("第 " + month + " 月总零件: " + number);
            System.out.println("第 " + month + " 月总工时: " + totalWorkload);

        }
    }

    /**
     * 生成外包任务报告
     */
    private void generateOutsourcedTasks() {
        if (!outsourcedTasks.isEmpty()) {
            System.out.println("=== 需要外包的任务（第1月无法完成） ===");
            System.out.println("外包任务数量: " + outsourcedTasks.size());

            double totalOutsourcedWorkload = 0;
            double number=0;
            for (TaskAssignment task : outsourcedTasks) {
                totalOutsourcedWorkload += task.getMakeCycle() * task.getAssignedQuantity();
                number+=task.getAssignedQuantity();
                //System.out.println("外包任务: " + task.getOrderCode() + ", 图号: " + task.getItemID() +
                      //  ", 数量: " + task.getAssignedQuantity() + ", 工时: " + (task.getMakeCycle() * task.getAssignedQuantity())+"截至日期"+task.getDeadline());
            }

            System.out.println("外包任务总工时: " + totalOutsourcedWorkload);
            System.out.println("外包任务总零件: " + number);
        } else {
            System.out.println("没有需要外包的任务");
        }
    }

    /**
     * 处理任务的主方法
     */
    public void processTasks(int startMonth, int endMonth) {
        if (startMonth < 1 || startMonth > 12 || endMonth < 1 || endMonth > 12 || startMonth > endMonth) {
            throw new IllegalArgumentException(
                    String.format("无效的月份范围: %d-%d，月份必须在1-12之间且起始月不能大于结束月", startMonth, endMonth));
        }

        System.out.println("开始处理任务 - 工作中心: " + workcenterName + ", 年份: " + year + ", 月份范围: " + startMonth + "-" + endMonth);

        // 从后向前处理月份，将无法完成的任务向前推
        for (int month = endMonth; month >= startMonth; month--) {
            System.out.println("处理第 " + month + " 月的任务");

            // 确保每个月都有一个overflow容器
            overflowTasks.putIfAbsent(month, new ArrayList<>());

            // 先尝试加载该月任务（如果尚未加载）
            if (!monthlyDemands.containsKey(month) || monthlyDemands.get(month).isEmpty()) {
                loadMonthlyTasks(month);
            }

            // 处理当月任务和溢出
            handleMonthlyOverflow(month);
        }

        // 生成报告
        generateProcessingReport();
        generateOutsourcedTasks();

        // 汇总统计
        int totalTasks = 0;
        for (List<TaskAssignment> tasks : finalTasks.values()) {
            totalTasks += tasks.size();
        }

        System.out.println("任务处理完成 - 已分配: " + totalTasks + ", 外包: " + outsourcedTasks.size() + ", 总计: " + (totalTasks + outsourcedTasks.size()));
    }

    /**
     * 初始化所有月份的产能和任务
     * 一次性为所有月份准备数据
     */
    public void initializeAllMonths(int startMonth, int endMonth, double dailyCapacity) {
        if (startMonth < 1 || startMonth > 12 || endMonth < 1 || endMonth > 12 || startMonth > endMonth) {
            throw new IllegalArgumentException("月份范围无效");
        }

        System.out.println("初始化" + year + "年" + startMonth + "月至" + endMonth + "月的产能和任务");

        double totalCapacity=0;
        double totalNeed=0;
        double totalNum=0;
        // 为每个月计算产能并加载任务
        for (int month = startMonth; month <= endMonth; month++) {
            // 计算产能
            totalCapacity+=calculateMonthlyCapacity(month, dailyCapacity);
            // 加载任务
            Map<Integer, Map<String, Double>> fin=loadMonthlyTasks(month);
            totalNeed+=fin.get(month).get("工时");
            totalNum+=fin.get(month).get("件数");
        }
        System.out.println("初始化完成");
        System.out.println("理论12个月总产能为： "+totalCapacity);
        System.out.println("理论12个月订单需求工时为："+totalNeed);
        System.out.println("理论12个月生产零件数量为："+totalNum);
    }
}